From: Koral Ilgun Date: Sat, 9 Mar 2024 03:33:58 +0000 (-0800) Subject: iwinfo: add basic IEEE 802.11be support X-Git-Url: http://git.openwrt.org/%22https:/collectd.org//%22http:/www.crowdsec.net/%22/%22https:/collectd.org/%22http:/www.crowdsec.net/%22?a=commitdiff_plain;h=268a662421fa03798881b34658a3d6bd6a30d97d;p=project%2Fiwinfo.git iwinfo: add basic IEEE 802.11be support Add support for IEEE 802.11be via HW and HT modelist as well as EHT specific rate information for associated STAs. Signed-off-by: Koral Ilgun Signed-off-by: Chad Monroe --- diff --git a/include/iwinfo.h b/include/iwinfo.h index b50de69..2a841be 100644 --- a/include/iwinfo.h +++ b/include/iwinfo.h @@ -31,6 +31,7 @@ enum iwinfo_80211 { IWINFO_80211_AC, IWINFO_80211_AD, IWINFO_80211_AX, + IWINFO_80211_BE, /* keep last */ IWINFO_80211_COUNT @@ -43,6 +44,7 @@ enum iwinfo_80211 { #define IWINFO_80211_AC (1 << IWINFO_80211_AC) #define IWINFO_80211_AD (1 << IWINFO_80211_AD) #define IWINFO_80211_AX (1 << IWINFO_80211_AX) +#define IWINFO_80211_BE (1 << IWINFO_80211_BE) extern const char * const IWINFO_80211_NAMES[IWINFO_80211_COUNT]; @@ -192,6 +194,12 @@ enum iwinfo_htmode { IWINFO_HTMODE_HE80, IWINFO_HTMODE_HE80_80, IWINFO_HTMODE_HE160, + IWINFO_HTMODE_EHT20, + IWINFO_HTMODE_EHT40, + IWINFO_HTMODE_EHT80, + IWINFO_HTMODE_EHT80_80, + IWINFO_HTMODE_EHT160, + IWINFO_HTMODE_EHT320, /* keep last */ IWINFO_HTMODE_COUNT @@ -210,6 +218,12 @@ enum iwinfo_htmode { #define IWINFO_HTMODE_HE80 (1 << IWINFO_HTMODE_HE80) #define IWINFO_HTMODE_HE80_80 (1 << IWINFO_HTMODE_HE80_80) #define IWINFO_HTMODE_HE160 (1 << IWINFO_HTMODE_HE160) +#define IWINFO_HTMODE_EHT20 (1 << IWINFO_HTMODE_EHT20) +#define IWINFO_HTMODE_EHT40 (1 << IWINFO_HTMODE_EHT40) +#define IWINFO_HTMODE_EHT80 (1 << IWINFO_HTMODE_EHT80) +#define IWINFO_HTMODE_EHT80_80 (1 << IWINFO_HTMODE_EHT80_80) +#define IWINFO_HTMODE_EHT160 (1 << IWINFO_HTMODE_EHT160) +#define IWINFO_HTMODE_EHT320 (1 << IWINFO_HTMODE_EHT320) extern const char * const IWINFO_HTMODE_NAMES[IWINFO_HTMODE_COUNT]; @@ -222,10 +236,13 @@ struct iwinfo_rate_entry { uint8_t is_ht:1; uint8_t is_vht:1; uint8_t is_he:1; + uint8_t is_eht:1; uint8_t he_gi; uint8_t he_dcm; uint8_t mhz; uint8_t nss; + uint8_t mhz_hi; + uint8_t eht_gi; }; struct iwinfo_assoclist_entry { diff --git a/include/iwinfo/utils.h b/include/iwinfo/utils.h index 7b8ceea..fbd7d6c 100644 --- a/include/iwinfo/utils.h +++ b/include/iwinfo/utils.h @@ -53,6 +53,7 @@ size_t iwinfo_format_hwmodes(int modes, char *buf, size_t len); int iwinfo_htmode_is_ht(int htmode); int iwinfo_htmode_is_vht(int htmode); int iwinfo_htmode_is_he(int htmode); +int iwinfo_htmode_is_eht(int htmode); int iwinfo_ifup(const char *ifname); int iwinfo_ifdown(const char *ifname); diff --git a/iwinfo_cli.c b/iwinfo_cli.c index 5dcee9a..6f87d98 100644 --- a/iwinfo_cli.c +++ b/iwinfo_cli.c @@ -327,6 +327,17 @@ static char * format_assocrate(struct iwinfo_rate_entry *r) p += snprintf(p, l, ", HE-DCM %d", r->he_dcm); l = sizeof(buf) - (p - buf); } + else if (r->is_eht) + { + p += snprintf(p, l, ", EHT-MCS %d, %dMHz", r->mcs, r->mhz_hi * 256 + r->mhz); + l = sizeof(buf) - (p - buf); + + p += snprintf(p, l, ", EHT-NSS %d", r->nss); + l = sizeof(buf) - (p - buf); + + p += snprintf(p, l, ", EHT-GI %d", r->eht_gi); + l = sizeof(buf) - (p - buf); + } } return buf; diff --git a/iwinfo_lib.c b/iwinfo_lib.c index 579efc4..f9f6569 100644 --- a/iwinfo_lib.c +++ b/iwinfo_lib.c @@ -30,6 +30,7 @@ const char * const IWINFO_80211_NAMES[IWINFO_80211_COUNT] = { "ac", "ad", "ax", + "be", }; const char * const IWINFO_BAND_NAMES[IWINFO_BAND_COUNT] = { @@ -92,7 +93,13 @@ const char * const IWINFO_HTMODE_NAMES[IWINFO_HTMODE_COUNT] = { "HE40", "HE80", "HE80+80", - "HE160" + "HE160", + "EHT20", + "EHT40", + "EHT80", + "EHT80+80", + "EHT160", + "EHT320", }; const char * const IWINFO_FREQ_FLAG_NAMES[IWINFO_FREQ_FLAG_COUNT] = { diff --git a/iwinfo_lua.c b/iwinfo_lua.c index ecf257d..fbe8c7c 100644 --- a/iwinfo_lua.c +++ b/iwinfo_lua.c @@ -279,7 +279,10 @@ static void set_rateinfo(lua_State *L, struct iwinfo_rate_entry *r, bool rx) lua_pushboolean(L, r->is_he); lua_setfield(L, -2, rx ? "rx_he" : "tx_he"); - lua_pushnumber(L, r->mhz); + lua_pushboolean(L, r->is_eht); + lua_setfield(L, -2, rx ? "rx_eht" : "tx_eht"); + + lua_pushnumber(L, r->mhz_hi * 256 + r->mhz); lua_setfield(L, -2, rx ? "rx_mhz" : "tx_mhz"); if (r->is_ht) @@ -293,7 +296,7 @@ static void set_rateinfo(lua_State *L, struct iwinfo_rate_entry *r, bool rx) lua_pushboolean(L, r->is_short_gi); lua_setfield(L, -2, rx ? "rx_short_gi" : "tx_short_gi"); } - else if (r->is_vht || r->is_he) + else if (r->is_vht || r->is_he | r->is_eht) { lua_pushnumber(L, r->mcs); lua_setfield(L, -2, rx ? "rx_mcs" : "tx_mcs"); @@ -309,6 +312,11 @@ static void set_rateinfo(lua_State *L, struct iwinfo_rate_entry *r, bool rx) lua_setfield(L, -2, rx ? "rx_he_dcm" : "tx_he_dcm"); } + if (r->is_eht) { + lua_pushnumber(L, r->eht_gi); + lua_setfield(L, -2, rx ? "rx_eht_gi" : "tx_eht_gi"); + } + if (r->is_vht) { lua_pushboolean(L, r->is_short_gi); lua_setfield(L, -2, rx ? "rx_short_gi" : "tx_short_gi"); @@ -554,6 +562,9 @@ static int iwinfo_L_hwmodelist(lua_State *L, int (*func)(const char *, int *)) lua_pushboolean(L, hwmodes & IWINFO_80211_AX); lua_setfield(L, -2, "ax"); + lua_pushboolean(L, hwmodes & IWINFO_80211_BE); + lua_setfield(L, -2, "be"); + return 1; } diff --git a/iwinfo_nl80211.c b/iwinfo_nl80211.c index 2200249..c352c9f 100644 --- a/iwinfo_nl80211.c +++ b/iwinfo_nl80211.c @@ -2047,7 +2047,17 @@ static void nl80211_parse_rateinfo(struct nlattr **ri, else if (ri[NL80211_RATE_INFO_BITRATE]) re->rate = nla_get_u16(ri[NL80211_RATE_INFO_BITRATE]) * 100; - if (ri[NL80211_RATE_INFO_HE_MCS]) + if (ri[NL80211_RATE_INFO_EHT_MCS]) + { + re->is_eht = 1; + re->mcs = nla_get_u8(ri[NL80211_RATE_INFO_EHT_MCS]); + + if (ri[NL80211_RATE_INFO_EHT_NSS]) + re->nss = nla_get_u8(ri[NL80211_RATE_INFO_EHT_NSS]); + if (ri[NL80211_RATE_INFO_EHT_GI]) + re->eht_gi = nla_get_u8(ri[NL80211_RATE_INFO_EHT_GI]); + } + else if (ri[NL80211_RATE_INFO_HE_MCS]) { re->is_he = 1; re->mcs = nla_get_u8(ri[NL80211_RATE_INFO_HE_MCS]); @@ -2084,6 +2094,8 @@ static void nl80211_parse_rateinfo(struct nlattr **ri, else if (ri[NL80211_RATE_INFO_80P80_MHZ_WIDTH] || ri[NL80211_RATE_INFO_160_MHZ_WIDTH]) re->mhz = 160; + else if (ri[NL80211_RATE_INFO_320_MHZ_WIDTH]) + re->mhz_hi = 320 / 256, re->mhz = 320 % 256; else re->mhz = 20; @@ -3155,6 +3167,7 @@ struct nl80211_modes uint16_t nl_ht; uint32_t nl_vht; uint16_t he_phy_cap[6]; + uint16_t eht_phy_cap[9]; }; static void nl80211_eval_modelist(struct nl80211_modes *m) @@ -3183,6 +3196,22 @@ static void nl80211_eval_modelist(struct nl80211_modes *m) m->ht |= IWINFO_HTMODE_HE160 | IWINFO_HTMODE_HE80_80; } + if (m->eht_phy_cap[0] != 0) { + m->hw |= IWINFO_80211_BE; + m->ht |= IWINFO_HTMODE_EHT20; + + if (m->he_phy_cap[0] & BIT(9)) + m->ht |= IWINFO_HTMODE_EHT40; + if (m->he_phy_cap[0] & BIT(10)) + m->ht |= IWINFO_HTMODE_EHT40 | IWINFO_HTMODE_EHT80; + if (m->he_phy_cap[0] & BIT(11)) + m->ht |= IWINFO_HTMODE_EHT160; + if (m->he_phy_cap[0] & BIT(12)) + m->ht |= IWINFO_HTMODE_EHT160 | IWINFO_HTMODE_EHT80_80; + if ((m->eht_phy_cap[0] & BIT(9)) && (m->bands & IWINFO_BAND_6)) + m->ht |= IWINFO_HTMODE_EHT320; + } + if (m->bands & IWINFO_BAND_24) { m->hw |= IWINFO_80211_B; @@ -3252,6 +3281,8 @@ static int nl80211_get_modelist_cb(struct nl_msg *msg, void *arg) nla_for_each_nested(nl_iftype, bands[NL80211_BAND_ATTR_IFTYPE_DATA], rem_band) { nla_parse(tb, NL80211_BAND_IFTYPE_ATTR_MAX, nla_data(nl_iftype), nla_len(nl_iftype), NULL); + + // HE if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]) { len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]); @@ -3261,6 +3292,17 @@ static int nl80211_get_modelist_cb(struct nl_msg *msg, void *arg) nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]), len); } + + // EHT + if (tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY]) { + len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY]); + + if (len > sizeof(m->eht_phy_cap) - 1) + len = sizeof(m->eht_phy_cap) - 1; + memcpy(&((uint8_t *)m->eht_phy_cap)[1], + nla_data(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY]), + len); + } } } } @@ -3325,6 +3367,7 @@ static int nl80211_get_htmode(const char *ifname, int *buf) char *res, b[2] = { 0 }; int err; bool he = false; + bool eht = false; res = nl80211_phy2ifname(ifname); *buf = 0; @@ -3335,6 +3378,9 @@ static int nl80211_get_htmode(const char *ifname, int *buf) if (err) return -1; + if (nl80211_hostapd_query(res ? res : ifname, "ieee80211be", b, sizeof(b))) + eht = b[0] == '1'; + if (nl80211_hostapd_query(res ? res : ifname, "ieee80211ax", b, sizeof(b))) he = b[0] == '1'; else if (nl80211_wpactl_query(res ? res : ifname, "wifi_generation", b, sizeof(b))) @@ -3343,7 +3389,7 @@ static int nl80211_get_htmode(const char *ifname, int *buf) switch (chn.width) { case NL80211_CHAN_WIDTH_20: if (he) - *buf = IWINFO_HTMODE_HE20; + *buf = (eht == true) ? IWINFO_HTMODE_EHT20 : IWINFO_HTMODE_HE20; else if (chn.mode == -1) *buf = IWINFO_HTMODE_VHT20; else @@ -3351,7 +3397,7 @@ static int nl80211_get_htmode(const char *ifname, int *buf) break; case NL80211_CHAN_WIDTH_40: if (he) - *buf = IWINFO_HTMODE_HE40; + *buf = (eht == true) ? IWINFO_HTMODE_EHT40 : IWINFO_HTMODE_HE40; else if (chn.mode == -1) *buf = IWINFO_HTMODE_VHT40; else @@ -3359,22 +3405,25 @@ static int nl80211_get_htmode(const char *ifname, int *buf) break; case NL80211_CHAN_WIDTH_80: if (he) - *buf = IWINFO_HTMODE_HE80; + *buf = (eht == true) ? IWINFO_HTMODE_EHT80 : IWINFO_HTMODE_HE80; else *buf = IWINFO_HTMODE_VHT80; break; case NL80211_CHAN_WIDTH_80P80: if (he) - *buf = IWINFO_HTMODE_HE80_80; + *buf = (eht == true) ? IWINFO_HTMODE_EHT80_80 : IWINFO_HTMODE_HE80_80; else *buf = IWINFO_HTMODE_VHT80_80; break; case NL80211_CHAN_WIDTH_160: if (he) - *buf = IWINFO_HTMODE_HE160; + *buf = (eht == true) ? IWINFO_HTMODE_EHT160 : IWINFO_HTMODE_HE160; else *buf = IWINFO_HTMODE_VHT160; break; + case NL80211_CHAN_WIDTH_320: + *buf = IWINFO_HTMODE_EHT320; + break; case NL80211_CHAN_WIDTH_5: case NL80211_CHAN_WIDTH_10: case NL80211_CHAN_WIDTH_20_NOHT: diff --git a/iwinfo_utils.c b/iwinfo_utils.c index d96cbb3..279c307 100644 --- a/iwinfo_utils.c +++ b/iwinfo_utils.c @@ -151,8 +151,8 @@ uint8_t iwinfo_ghz2band(uint32_t ghz) size_t iwinfo_format_hwmodes(int modes, char *buf, size_t len) { - // bit numbers as per IWINFO_80211_*: ad ac ax a b g n - const int order[IWINFO_80211_COUNT] = { 5, 4, 6, 0, 1, 2, 3 }; + // bit numbers as per IWINFO_80211_*: ad ac ax a b be g n + const int order[IWINFO_80211_COUNT] = { 5, 4, 6, 0, 1, 7, 2, 3 }; size_t res = 0; int i; @@ -216,6 +216,22 @@ int iwinfo_htmode_is_he(int htmode) return 0; } +int iwinfo_htmode_is_eht(int htmode) +{ + switch (htmode) + { + case IWINFO_HTMODE_EHT20: + case IWINFO_HTMODE_EHT40: + case IWINFO_HTMODE_EHT80: + case IWINFO_HTMODE_EHT80_80: + case IWINFO_HTMODE_EHT160: + case IWINFO_HTMODE_EHT320: + return 1; + } + + return 0; +} + int iwinfo_ifup(const char *ifname) { struct ifreq ifr;